package com.om.base;

import java.io.*;
import java.sql.*;
import java.util.*;
import java.util.Date;



import com.om.common.ConfigReader;
import com.om.common.TimeStampToInt;

/**
 * 数据库对象管理器
 * 把数据库连接和当前调用的线程进行绑定，在线程结束的时候统一对相关的数据库连接进行回收
 * 保证了同一次请求里面对于相同配置的数据库连接只会打开一次，同时也防止了数据库连因为忘记
 * 关闭而造成的连接耗尽
 * @author tangchuan
 *
 */
public class DBConnectionManager {
	
	public final static String DEFAULT_NAME="default";
	private static  DBConnectionManager instance;

	private static int clients=0;

	

	
	//private Vector drivers = new Vector();

	//private HashMap<Integer,HashMap<String,Connection>> threadOpenedConnections = new HashMap<Integer, HashMap<String,Connection>>();
	//private  HashMap<Integer,HashMap<String,Connection>> threadOpenedConnections = new HashMap<Integer, HashMap<String,Connection>>();
	
	private static ThreadLocal<HashMap<String,Connection>> threadOpenedConnections = new ThreadLocal<HashMap<String,Connection>>();
	
	private static ArrayList<ReleaseConnection> ReleasedList = new ArrayList<ReleaseConnection>();


	

	private Hashtable<Integer,String> openedConnectonList = new Hashtable<Integer,String>();
	
	//private HashMap<Integer,BaseConnectionAdapter> adapters = new HashMap<Integer,BaseConnectionAdapter>();
	private static ThreadLocal<BaseConnectionAdapter> adapters = new ThreadLocal<BaseConnectionAdapter>();
	
	
	/**
	 * 获取DBConnectionManager的一个单例
	 * @return
	 */
	public static synchronized  DBConnectionManager getInstance() {
		if (instance == null) {
			instance = new DBConnectionManager();
		}
		clients++;
		return instance;
	}

	
	/**
	 * 设置用来获取数据库配置的ConnectionAdapter对象
	 * @param connectionAdapter ConnectionAdapter对象
	 */
	public void setConnectionAdapter(BaseConnectionAdapter connectionAdapter) {
		/*if(!adapters.containsKey(Thread.currentThread().hashCode())){
			this.adapters.put(Thread.currentThread().hashCode(), connectionAdapter);
		}*/
		this.adapters.set(connectionAdapter);
	}
	
	
	

	/**
	 * 获取数据库配置的ConnectionAdapter对象
	 * @return ConnectionAdapter对象
	 */
	public BaseConnectionAdapter getConnectionAdapter() {
		BaseConnectionAdapter adapter = this.adapters.get();
		/*if(this.adapters.containsKey(Thread.currentThread().hashCode())){
			adapter =this.adapters.get(Thread.currentThread().hashCode());
		}*/
		

		return adapter;
		//this.connectionAdapter = connectionAdapter;
	}
	
	/**
	 * 释放一个连接对象
	 * @param con 连接对象
	 */
	public void freeConnection(Connection con)  {
		try{
			
			int hashCode = con.hashCode();
			System.out.println("["+TimeStampToInt.systemTime() +"]:  ======================Connection "+ hashCode
					+ " has been closed by thread:" + Thread.currentThread().hashCode()+"======================");
					
			
			if(con!=null && !con.isClosed()){
				con.close();
			}
			HashMap<String,Connection> openedConns = null;
			
			if(threadOpenedConnections.get()!=null){
			//if (threadOpenedConnections.containsKey(Thread.currentThread().hashCode())) {
					openedConns = threadOpenedConnections.get();
					if(openedConnectonList.containsKey(hashCode)){
						 String name = (String)openedConnectonList.get(hashCode);
						 if(openedConns!= null && openedConns.containsKey(name )){
							 openedConns.remove(name);
						 }
						 openedConnectonList.remove(hashCode);
					}
					
			}
			
			
			
		}catch(Exception ex){
			ex.printStackTrace();
		}
		

	}
	
	/**
	 * 释放指定线程打开的所有数据库连接对象
	 * @param threadId 需要释放的线程HashCode() 
	 */
	public  void freeThreadOpenedConnections(Integer threadId) {
		try {
			//if (threadOpenedConnections.containsKey(threadId)) {
			if (threadOpenedConnections.get()!=null) {
				HashMap<String,Connection> openedConns = threadOpenedConnections.get();
				Collection<Connection> conns = openedConns.values();
				
				while(conns.iterator().hasNext()){
					Connection conn =conns.iterator().next();
					freeConnection(conn);
					conns.remove(conn);
				}
				/*if(this.adapters.containsKey(threadId)){
					this.adapters.remove(this.adapters);
				}*/
				if(this.adapters.get()!=null){
					this.adapters.remove();
				}
				
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	/**
	 * 通过配置文件中的key值获取一个指定配置的数据库连接对象
	 * 该对象被当前线程托管，线程结束的时候当前连接对象会自动被释放，不用手动调用close方法去关闭
	 * @param key 配置文件中的一个配置项名称
	 * @return 一个可用的数据库连接对象
	 */
	public  Connection getConnection(String key) {
		
		Connection conn =null;

		try {
			//openedConnectonList.put(conn.hashCode(), name);
			HashMap<String,Connection> openedConns = null;

			//if (threadOpenedConnections.containsKey(Thread.currentThread().hashCode())) {
			if (threadOpenedConnections.get()!=null) {
					//openedConns = (HashMap<String,Connection>) threadOpenedConnections.get(Thread.currentThread().hashCode());
				openedConns =threadOpenedConnections.get();
			}
			if(openedConns!=null && openedConns.containsKey(key)){
				conn = openedConns.get(key);
				
			}
			if(conn == null){
				conn = this.getConnectionAdapter().getNewConnection(key);
			}
			
		} catch (Exception ex) {
			ex.printStackTrace();
		}		
		
		
		return conn;
	}
	
	public  Connection getConnection(String key,boolean forceOpenNew) {
		
		Connection conn =null;

		try {
			//openedConnectonList.put(conn.hashCode(), name);
			HashMap<String,Connection> openedConns = null;

			//if (threadOpenedConnections.containsKey(Thread.currentThread().hashCode())) {
			if (threadOpenedConnections.get()!=null) {
					openedConns = threadOpenedConnections.get();
			}
			if(openedConns!=null && openedConns.containsKey(key)){
				conn = openedConns.get(key);
				
			}
			if(conn == null && forceOpenNew){
				conn = this.getConnectionAdapter().getNewConnection(key);
			}
			
		} catch (Exception ex) {
			ex.printStackTrace();
		}		
		
		
		return conn;
	}
	
	/**
	 * 根据默认的配置返回一个打开的数据库连接对象
	 * 该对象被当前线程托管，线程结束的时候当前连接对象会自动被释放，不用手动调用close方法去关闭
	 * @return 一个可用的数据库连接对象
	 */
	public  Connection getConnection() {
		Connection conn =null;
		try {
			BaseConnectionAdapter connectionAdapter = this.getConnectionAdapter();
			if(connectionAdapter!=null){
				conn = this.getConnectionAdapter().getAvailableConnection();
			}
			else{
				conn = this.getConnection(DEFAULT_NAME);
			}
			
			
		} catch (Exception ex) {
			ex.printStackTrace();
		}		
		return conn;
	}
	
	public  Connection getConnection(boolean forceOpenNew) {
		Connection conn =null;
		try {
			conn = this.getConnectionAdapter().getAvailableConnection(forceOpenNew);
			
		} catch (Exception ex) {
			ex.printStackTrace();
		}		
		return conn;
	}
	
	/**
	 * 根据默认的配置返回一个打开的用于进行写操作的数据库连接对象（多用于数据的insert,update,delete操作）
	 * 该对象被当前线程托管，线程结束的时候当前连接对象会自动被释放，不用手动调用close方法去关闭
	 * @return 一个可用的数据库连接对象
	 */
	public  Connection getWriteConnection() {
		
		Connection conn =null;
		try {
			conn = this.getConnectionAdapter().getWriteConnection();
			
		} catch (Exception ex) {
			ex.printStackTrace();
		}		
		return conn;
	}

	/**
	 * 把一个数据库对象提交给当前线程进行托管
	 * 托管后该对象的回收由当前线程来控制，不需要手动调用close方法
	 * @param name 连接对象的配置名称
	 * @param conn 需要托管的连接对象
	 */
	public  void setConnection(String name,Connection conn) {
		

		try {
			//openedConnectonList.put(conn.hashCode(), name);
			HashMap<String,Connection> openedConns = new HashMap<String,Connection>();
			
			//if (threadOpenedConnections.containsKey(Thread.currentThread().hashCode())) {
			if (threadOpenedConnections.get()!=null) {
				//
				openedConns =threadOpenedConnections.get();
				//openedConns = (HashMap)threadOpenedConnections.get(Thread.currentThread().hashCode());
			}

			if (openedConns != null) {
				openedConns.put(name, conn);
			}
			//HashMap<String,Connection> map
			threadOpenedConnections.set(openedConns);
			openedConnectonList.put(conn.hashCode(), name);
			
			System.out.println("["+TimeStampToInt.systemTime() +"]: Connection "
					+ conn.hashCode()
					+ " has been opened by thread:" + Thread.currentThread().hashCode());
			
			
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		
	}
	
	public  void setConnection(Connection conn) {
		this.setConnection(DEFAULT_NAME,conn);
	}

	

	

	
	
	
	

	
}
